#pragma once
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <memory>
#include <pthread.h>
#include <cstring>
#define NUMSIZE 10240
#define wwwroot "/myhtml.html"
#define FLAG "\r\n"
class sreve;
struct data
{
    int _sock;
    sreve *_str;
    data(int sock, sreve *str) : _sock(sock), _str(str)
    {
    }
};
class sreve
{
public:
    sreve(char *port) : _port(port)
    {
        int listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (listensock < 0)
        {
            std::cout << "listensock enrro" << std::endl;
            exit(1);
        }
        _listensock = listensock;
        sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(atoi(_port));
        local.sin_addr.s_addr = inet_addr("0.0.0.0");
        socklen_t len = sizeof(local);
        int ret = bind(listensock, (sockaddr *)&local, len);
        if (ret < 0)
        {
            std::cout << "bind enrro" << std::endl;
            exit(2);
        }
        int listens = listen(listensock, 20);
        if (listens < 0)
        {
            std::cout << "listens enrro" << std::endl;
            exit(3);
        }
    }
    void start()
    {
        while (true)
        {
            sockaddr_in client;
            //memset(&client,0,sizeof(client));
            //std::cout<<"测试前"<<client.sin_port<<std::endl;
            socklen_t len = sizeof(client);
            int sersock = accept(_listensock, (sockaddr *)&client, &len);
            //std::cout << sersock << std::endl;
            if (sersock < 0)
            {
                std::cout << "accept enrro" << std::endl;
                continue;
            }
            //std::cout<<"测试后"<<client.sin_port<<std::endl;
            //创建一个新线程
            createp(sersock);
        }
    }
    // 切割字符串,取到请求行
    std::string cut(std::string &tmp)
    {
        size_t pos = tmp.find("\r\n");
        // std::cout<<tmp.substr(0, pos).size()<<std::endl;
        // std::cout << tmp.substr(0, pos) << std::endl;
        return tmp.substr(0, pos);
    }
    // 切割字符串，取到文件路径
    std::string cutc(std::string &tmp)
    {
        size_t pos = tmp.find(" ");
        std::string val = tmp.substr(pos + 1);
        // std::cout << val.c_str() << std::endl;
        pos = val.find(" ");
        // std::cout<<pos<<std::endl;
        val = val.substr(0, pos);
        // std::cout << val.c_str() << std::endl;
        return val;
    }
    // 进行请求
    static void *fun_(void *args)
    {
        pthread_detach(pthread_self());
        data *p = static_cast<data *>(args);
        char buffer[NUMSIZE];
        memset(buffer, 0, sizeof(NUMSIZE));
        ssize_t s = recv(p->_sock, buffer, NUMSIZE - 1, 0);
        if (s > 0)
        {
            // std::cout << buffer << std::endl;
            std::string cutstr = buffer;
            std::string content;
            std::string respon;
            // 切割字符串拿到路径
            std::string file = "./wwwroot";
            std::string rowstr = p->_str->cut(cutstr);
            file += p->_str->cutc(rowstr);
            // 打开文件并且读取
            memset(buffer, 0, sizeof(NUMSIZE));
            // 如果是web根目录
            if (strcmp(file.c_str(), "./wwwroot/") == 0)
            {
                // 如果是web根目录
                memset(buffer, 0, sizeof(NUMSIZE));
                int fd = open("./wwwroot/myhtml.html", O_RDONLY);
                if (fd > 0)
                {
                    while (true)
                    {
                        ssize_t s = read(fd, buffer, NUMSIZE - 1);
                        if (s > 0)
                            content += buffer;
                        else
                        {
                            close(fd);
                            break;
                        }
                    }
                }
                respon = "HTTP/1.1 200 OK\r\n";
                //respon+="Connection: keep-alive\r\n";
                respon += "\r\n";
                respon += content;
                // std::cout << respon.c_str() << std::endl;
                send(p->_sock, respon.c_str(), respon.size(), 0);
                // close(fd);
            }
            // 如果不是根目录
            else
            {
                memset(buffer, 0, sizeof(NUMSIZE));
                int fd = open(file.c_str(), O_RDONLY);
                // std::cout << fd << file.c_str() << std::endl;
                //  找到路径
                if (fd > 0)
                {
                    while (true)
                    {
                        ssize_t s = read(fd, buffer, NUMSIZE - 1);
                        if (s > 0)
                            content += buffer;
                        else
                        {
                            close(fd);
                            break;
                        }
                    }
                    // 加http报头文件正文内容
                    respon = "HTTP/1.1 200 OK\r\n";
                    respon += "\r\n";
                    respon += content;
                    // std::cout << respon.c_str() << std::endl;
                    //  发送响应
                    send(p->_sock, respon.c_str(), respon.size(), 0);
                    // close(fd);
                }
                // 找不到路径
                else
                {
                    respon = "HTTP/1.1 404 Notfound\r\n";
                    respon += "\r\n";
                    // std::cout << respon.c_str() << std::endl;
                    send(p->_sock, respon.c_str(), respon.size(), 0);
                }
            }
        }
        // 关闭sersock
        close(p->_sock);
        delete p;
        return nullptr;
    }
    ~sreve()
    {
        std::cout << "服务端退出" << std::endl;
    }

private:
    char *_port;
    int _listensock;
    // 创建线程
    void createp(int sersock)
    {
        pthread_t tid;
        data *p = new data(sersock, this);
        pthread_create(&tid, nullptr, fun_, p);
    }
};
